<?php
declare(strict_types=1);

namespace app\controller\user;

use app\BaseController;
use app\model\{Order, User, ExpressServiceProvider, Coupon};
use app\service\{WechatService, AlipayService};
use think\facade\{Db, Log, Cache};
use think\Request;

class OrderController extends BaseController
{
    /**
     * 获取订单列表
     */
    public function index(Request $request)
    {
        $where = [
            ['user_id', '=', $request->userId],
            ['merchant_id', '=', $request->merchantId]
        ];
        
        // 订单状态筛选
        if ($status = $request->param('status')) {
            $where[] = ['order_status', '=', $status];
        }
        
        // 游标ID
        $last_id = (int)$request->param('last_id', 0);
        if ($last_id > 0) {
            $where[] = ['id', '<', $last_id];
        }
        
        // 每页条数
        $limit = (int)$request->param('limit', 15);
        
        $list = Order::where($where)
            ->order('id', 'desc')
            ->limit($limit + 1)
            ->select();
            
        $has_more = false;
        if (count($list) > $limit) {
            $has_more = true;
            $list = array_slice($list->toArray(), 0, $limit);
        } else {
            $list = $list->toArray();
        }
        
        // 获取下一页的游标ID
        $next_id = 0;
        if ($has_more && !empty($list)) {
            $next_id = end($list)['id'];
        }
        
        return $this->success('获取成功', [
            'list' => $list,
            'has_more' => $has_more,
            'next_id' => $next_id
        ]);
    }
    
    /**
     * 创建订单
     */
    public function create(Request $request)
    {
        $data = $this->validate($request->post(), [
            'company_code' => 'require',
            'sender_name' => 'require|max:20',
            'sender_phone' => 'require|mobile',
            'sender_province' => 'require',
            'sender_city' => 'require',
            'sender_county' => 'require',
            'sender_address' => 'require|max:100',
            'receiver_name' => 'require|max:20',
            'receiver_phone' => 'require|mobile',
            'receiver_province' => 'require',
            'receiver_city' => 'require',
            'receiver_county' => 'require',
            'receiver_address' => 'require|max:100',
            'weight_estimate' => 'require|float|>:0',
            'insure_amount' => 'float|>=:0',
            'coupon_id' => 'integer|>=:0'
        ]);
        
        Db::startTrans();
        try {
            // 计算运费
            $express = ExpressServiceProvider::where('company_code', $data['company_code'])->find();
            if (!$express) {
                throw new \Exception('快递公司不存在');
            }
            
            // 计算预估运费
            $fee = $this->calculateFee($express, $data);
            
            // 创建订单
            $order = Order::create([
                'merchant_id' => $request->merchantId,
                'user_id' => $request->userId,
                'order_no' => $this->generateOrderNo(),
                'company_code' => $data['company_code'],
                'sender_name' => $data['sender_name'],
                'sender_phone' => $data['sender_phone'],
                'sender_province' => $data['sender_province'],
                'sender_city' => $data['sender_city'],
                'sender_county' => $data['sender_county'],
                'sender_address' => $data['sender_address'],
                'receiver_name' => $data['receiver_name'],
                'receiver_phone' => $data['receiver_phone'],
                'receiver_province' => $data['receiver_province'],
                'receiver_city' => $data['receiver_city'],
                'receiver_county' => $data['receiver_county'],
                'receiver_address' => $data['receiver_address'],
                'weight_estimate' => $data['weight_estimate'],
                'fee_estimate' => $fee['total'],
                'insure_amount' => $data['insure_amount'] ?? 0,
                'item_type' => $data['item_type'] ?? 1,
                'insure_fee' => $fee['insure'],
                'coupon_id' => $data['coupon_id'] ?? 0,
                'coupon_amount' => $fee['coupon'],
                'create_time' => date('Y-m-d H:i:s')
            ]);
            
            Db::commit();
            return $this->success('创建成功', [
                'order_id' => $order->id,
                'order_no' => $order->order_no
            ]);
        } catch (\Exception $e) {
            Db::rollback();
            return $this->error($e->getMessage());
        }
    }
    
    /**
     * 取消订单
     */
    public function cancel(Request $request, $id)
    {
        Db::startTrans();
        try {
            $order = Order::where([
                'id' => $id,
                'user_id' => $request->userId,
                'merchant_id' => $request->merchantId
            ])->find();
            
            if (!$order) {
                throw new \Exception('订单不存在');
            }
            
            if (!in_array($order->order_status, [0, 1])) {
                throw new \Exception('当前状态不能取消');
            }
            
            // 如果已支付则退款
            if ($order->pay_status == 1) {
                $this->handleRefund($order);
            }
            
            $order->save([
                'order_status' => 98,
                'cancel_time' => date('Y-m-d H:i:s'),
                'cancel_reason' => '用户取消'
            ]);
            
            Db::commit();
            return $this->success('取消成功');
        } catch (\Exception $e) {
            Db::rollback();
            return $this->error($e->getMessage());
        }
    }
    
    /**
     * 处理退款
     */
    protected function handleRefund($order)
    {
        if ($order->payment_method == 'wechat') {
            $wechatService = new WechatService($order->merchant_id);
            $result = $wechatService->refund([
                'out_trade_no' => $order->order_no,
                'total_fee' => $order->fee_actual * 100,
                'refund_fee' => $order->fee_actual * 100,
                'refund_desc' => '订单取消退款'
            ]);
        } else if ($order->payment_method == 'alipay') {
            $alipayService = new AlipayService($order->merchant_id);
            $result = $alipayService->refund([
                'out_trade_no' => $order->order_no,
                'refund_amount' => $order->fee_actual,
                'refund_desc' => '订单取消退款'
            ]);
        }
        
        if (!$result) {
            throw new \Exception('退款失败');
        }
        
        // 更新订单退款状态
        $order->save([
            'refund_status' => 2,
            'refund_time' => date('Y-m-d H:i:s'),
            'refund_amount' => $order->fee_actual,
            'refund_remark' => '订单取消退款'
        ]);
    }
    
    /**
     * 生成订单号
     */
    protected function generateOrderNo()
    {
        return date('YmdHis') . mt_rand(1000, 9999);
    }
    
    /**
     * 订单支付
     */
    public function pay(Request $request, $id)
    {
        $payment_method = $request->param('payment_method');
        if (!in_array($payment_method, ['wechat', 'alipay', 'balance'])) {
            return $this->error('支付方式错误');
        }
        
        Db::startTrans();
        try {
            $order = Order::where([
                'id' => $id,
                'user_id' => $request->userId,
                'merchant_id' => $request->merchantId,
                'order_status' => 0,
                'pay_status' => 0
            ])->find();
            
            if (!$order) {
                throw new \Exception('订单不存在或已支付');
            }
            
            // 余额支付
            if ($payment_method == 'balance') {
                $user = User::find($request->userId);
                if ($user->balance < $order->fee_estimate) {
                    throw new \Exception('余额不足');
                }
                
                // 扣除余额
                $user->dec('balance', $order->fee_estimate)->update();
                
                // 更新订单状态
                $order->save([
                    'payment_method' => 'balance',
                    'fee_actual' => $order->fee_estimate,
                    'pay_status' => 1,
                    'pay_time' => date('Y-m-d H:i:s')
                ]);
                
                Db::commit();
                return $this->success('支付成功');
            }
            
            // 微信支付
            if ($payment_method == 'wechat') {
                $wechatService = new WechatService($order->merchant_id);
                $result = $wechatService->createOrder([
                    'out_trade_no' => $order->order_no,
                    'total_fee' => $order->fee_estimate * 100,
                    'body' => '快递费用',
                    'openid' => $request->user->openid
                ]);
                
                Db::commit();
                return $this->success('获取支付参数成功', $result);
            }
            
            // 支付宝支付
            if ($payment_method == 'alipay') {
                $alipayService = new AlipayService($order->merchant_id);
                $result = $alipayService->createOrder([
                    'out_trade_no' => $order->order_no,
                    'total_amount' => $order->fee_estimate,
                    'subject' => '快递费用'
                ]);
                
                Db::commit();
                return $this->success('获取支付参数成功', $result);
            }
        } catch (\Exception $e) {
            Db::rollback();
            return $this->error($e->getMessage());
        }
    }
    
    /**
     * 查询物流
     */
    public function logistics(Request $request, $id)
    {
        try {
            $order = Order::where([
                'id' => $id,
                'user_id' => $request->userId,
                'merchant_id' => $request->merchantId
            ])->find();
            
            if (!$order) {
                throw new \Exception('订单不存在');
            }
            
            if (!$order->express_no) {
                throw new \Exception('暂无物流信息');
            }
            
            // 从缓存获取物流信息
            $cacheKey = "logistics:{$order->company_code}:{$order->express_no}";
            $logistics = Cache::get($cacheKey);
            
            if (!$logistics) {
                // 调用快递100查询
                $kuaidi100 = new \app\service\Kuaidi100Service();
                $logistics = $kuaidi100->query([
                    'com' => $order->company_code,
                    'num' => $order->express_no
                ]);
                
                // 缓存物流信息(10分钟)
                if ($logistics) {
                    Cache::set($cacheKey, $logistics, 600);
                }
            }
            
            return $this->success('获取成功', [
                'express_no' => $order->express_no,
                'company_code' => $order->company_code,
                'traces' => $logistics
            ]);
        } catch (\Exception $e) {
            return $this->error($e->getMessage());
        }
    }
    
    /**
     * 计算运费
     */
    protected function calculateFee($express, $data)
    {
        // 基础运费计算
        $weight = $data['weight_estimate'];
        $fee = [
            'base' => 0,    // 基础运费
            'insure' => 0,  // 保价费
            'coupon' => 0,  // 优惠券抵扣
            'total' => 0    // 总费用
        ];
        
        // 首重费用
        if ($weight <= 1) {
            $fee['base'] = $express->first_weight_price;
        } else {
            // 续重费用
            $fee['base'] = $express->first_weight_price + 
                ceil($weight - 1) * $express->continued_weight_price;
        }
        
        // 保价费
        if (!empty($data['insure_amount']) && $data['insure_amount'] > 0) {
            $fee['insure'] = ceil($data['insure_amount'] * $express->insure_rate);
        }
        
        // 优惠券抵扣
        if (!empty($data['coupon_id'])) {
            $coupon = Coupon::find($data['coupon_id']);
            if ($coupon) {  
                $fee['coupon'] = $coupon->amount;
            }
        }
        
        // 计算总费用
        $fee['total'] = $fee['base'] + $fee['insure'] - $fee['coupon'];
        
        return $fee;
    }
} 